package network

import (
	"sync"
)

// 会话管理对象
type sessionMng[T any] struct {
	mutex    sync.RWMutex
	sessions map[uint64]*session[T] // 会话映射表 sessionID --> session
	comm     *Communicator[T]       // 所属通信对象
}

// newSessionMng Create a new session manager.
func newSessionMng[T any](comm *Communicator[T]) *sessionMng[T] {
	mng := new(sessionMng[T])
	mng.sessions = make(map[uint64]*session[T])
	mng.comm = comm
	return mng
}

// Count Calculate count of already connected session.
func (mng *sessionMng[T]) Count() int {
	mng.mutex.RLock()
	defer mng.mutex.RUnlock()

	return len(mng.sessions)
}

// Add Addition one session to session manager.
func (mng *sessionMng[T]) Add(session *session[T]) {
	mng.mutex.Lock()
	defer mng.mutex.Unlock()

	if _, ok := mng.sessions[session.guid]; ok {
		mng.comm.log.Errorf("SessionMng", "repated session %v, will override it", session.guid)
	}

	mng.sessions[session.guid] = session
}

// Remove Remove one session from session manager by session id.
func (mng *sessionMng[T]) Remove(guid uint64) {
	mng.mutex.Lock()
	defer mng.mutex.Unlock()

	delete(mng.sessions, guid)
}

// Get Get on session from session manager by session id.
// If session id corresponding session is not exist, will return nil.
func (mng *sessionMng[T]) Get(guid uint64) *session[T] {
	mng.mutex.RLock()
	defer mng.mutex.RUnlock()

	return mng.sessions[guid]
}

// RemoveAll Remove all of sessions in session manager,
// and return the removed session.
func (mng *sessionMng[T]) RemoveAll() (list []*session[T]) {
	mng.mutex.Lock()
	defer mng.mutex.Unlock()

	for _, session := range mng.sessions {
		list = append(list, session)
	}

	mng.sessions = make(map[uint64]*session[T])

	return
}

// GetAll Return a list of already exist session.
func (mng *sessionMng[T]) GetAll() (list []*session[T]) {
	mng.mutex.RLock()
	defer mng.mutex.RUnlock()

	for _, session := range mng.sessions {
		list = append(list, session)
	}

	return
}
